/**
 * 公共函数
 */

//引入Q模块
var Q = require('q');
//引入http模块用于创建httpServer
var http = require('http');
//引入fileSystem模块操作文件
var fs = require('fs');
//引入子进程模块用于执行shell
var childProcess = require('child_process');
//引入querystring模块操作查询字符串
var qs = require('querystring');
//引入multiparty
var mp = require('multiparty');
//引入request模块用于发起请求
var request = require('request');
//引入crypto模块用于加密
var crypto = require('crypto');
//引入xml2js模块用于json字符串与xml字符串互相转换
var xml2js = require('xml2js');
//引入种子随机数生成模块
let seedrandom = require('seedrandom');

//建立http服务器函数
var createHttpServer = function(config, requestHandler) {
	var deferred = Q.defer();
	//声明http服务器变量
	var httpServer = null;
	//如果开启了ssl就引入https模块否则引入http模块
	//建立http服务器并返回实例
	if(config.ssl) {
		http = require('https');
		//ssl需要引入证书key和cert
		httpServer = http.createServer({
			key: fs.readFileSync(config.sslKey),
			cert: fs.readFileSync(config.sslCert)
		}, requestHandler).listen(config.serverPort);
		deferred.resolve(httpServer);
	}
	else {
		http = require('http');
		httpServer = http.createServer(requestHandler).listen(config.serverPort);
		deferred.resolve(httpServer);
	}
	return deferred.promise;
}

//判断是否GET数据函数
var isGet = function(req) {
	var deferred = Q.defer();
	if(req.method.toUpperCase() == 'GET') {
		deferred.resolve();
	}
	else {
		deferred.reject();
	}
	return deferred.promise;
}

//判断是否POST数据函数
var isPost = function(req) {
	var deferred = Q.defer();
	if(req.method.toUpperCase() == 'POST') {
		deferred.resolve();
	}
	else {
		deferred.reject();
	}
	return deferred.promise;
}

//判断变量是否设置值函数
var isSet = function() {
	var deferred = Q.defer();
	var passNum = 0;
	var paramSum = Object.keys(arguments).length;
	if(paramSum == 0) {
		deferred.reject();
	}
	for(var index in arguments) {
		if(typeof(arguments[index]) != 'undefined' && arguments[index] != null) {
			passNum++;
		}
		if(parseInt(index) == paramSum - 1) {
			if(passNum == paramSum) {
				deferred.resolve(arguments);
			}
			else {
				deferred.reject();
			}
		}
	}
	return deferred.promise;
}

//判断变量是否为空函数
var isEmpty = function(value) {
	var deferred = Q.defer();
	//是否已设置值
	isSet(value).then(function() {
		if(value == '' || value == 0) {
			deferred.resolve(value);
		}
		else {
			deferred.reject();
		}
	}, function() {
		deferred.reject();
	});
	return deferred.promise;
}

//判断变量是否为字符串函数
var isString = function(value) {
	var deferred = Q.defer();
	isEmpty(value).then(function() {
		deferred.reject();
	}, function() {
		//判断是否为字符串类型
		if(Object.prototype.toString.call(value) === '[object String]') {
			deferred.resolve(value);
		}
		else {
			deferred.reject();
		}
	});
	return deferred.promise;
}

//判断变量是否json字符串函数
var isJson = function(value) {
	var deferred = Q.defer();
	//判断是否为字符串
	isString(value).then(function() {
		//尝试将字符串转换成json，如果失败则不是合法json字符串
		try {
			var result = JSON.parse(value);
			//判断结果是否是一个对象
			if(typeof(result) == 'object') {
				//是对象
				deferred.resolve(result);
			}
			//不是对象
			deferred.reject();
		}
		catch(e) {
			//非法json字符串
			deferred.reject();
		}
	}, deferred.reject);
	return deferred.promise;
}

//判断变量是否为数组函数
var isArray = function(value) {
	var deferred = Q.defer();
	//是否已设置值
	isSet(value).then(function() {
		//判断是否是数组类型
		if(Object.prototype.toString.call(value) == '[object Array]') {
			deferred.resolve(value);
		}
		else {
			deferred.reject();
		}
	}, function() {
		deferred.reject();
	});
	return deferred.promise;
}

//执行shell命令函数
var execShell = function(command) {
	var deferred = Q.defer();
	//开启子线程执行命令并返回结果
	childProcess.exec(command, function(err, stdOut, stdErr) {
		if(err || stdErr) {
			//执行出现错误
			deferred.reject({
				err: err,
				stdErr: stdErr
			});
		}
		else {
			//执行完毕并返回输出内容
			deferred.resolve(stdOut);
		}
	});
	return deferred.promise;
}

//字符串转换成对象
var string2obj = function(contentType, string, req) {
	var deferred = Q.defer();
	//尝试将字符串转换为对象
	try {
		switch(contentType) {
			case 'application/x-www-form-urlencoded':
				//使用querystring将字符串转换成对象
				deferred.resolve(qs.parse(string));
			break;
			case 'application/json':
			case 'text/xml':
				//将json字符串转换成对象
				deferred.resolve(JSON.parse(string));
			break;
			case 'multipart/form-data':
			case 'multipart/form-data; boundary=--------------------------370019552413530280557996':
				var form = new mp.Form();
				form.parse(req, function(err, fields, files) {
					if(err) {
						deferred.reject();
					}
					else {
						deferred.resolve({
							fields: fields,
							files: files
						});
					}
				});
			break;
			default:
				deferred.resolve(string);
		}
	}
	catch(e) {
		//转换失败
		deferred.reject();
	}
	return deferred.promise;
}

//判断文件是否存在函数
var fsExists = function(filePath) {
	var deferred = Q.defer();
	fs.access(filePath, fs.constants.F_OK, (err) => {
		err ? deferred.reject() : deferred.resolve(filePath);
	});
	return deferred.promise;
}

//新建文件夹函数
let fsMkdir = function(filePath) {
	let deferred = Q.defer();
	console.log('新建文件夹' + filePath);
	fs.mkdir(filePath, function(err) {
		if(err) {
			console.log(err);
			deferred.reject();
		}
		else {
			deferred.resolve();
		}
	});
	return deferred.promise;
}

//获取错误字符串函数
var getError = function(errCode) {
	var deferred = Q.defer();
	//错误码列表
	var errList = {
		//找不到接口文件
		'-0001': 'interface not found',
		//无权限调用接口
		'-0002': 'interface permission denied',
		//从redis读取3rsSession失败
		'-0003': 'redis getVal failed',
		//3rdSession指向数据不存在或有误
		'-0004': '3rdSession include params error',
		//redis服务器未在运行
		'-0005': 'redis server not running',
		//登录接口参数非法
		'-0006': 'login params illegal',
		//获取sessionKey失败
		'-0007': 'get sessionKey failed',
		//解密用户数据失败
		'-0008': 'encrypt userdata failed',
		//生成3rdSession失败
		'-0009': 'create 3rdSession failed',
		//存储用户数据失败
		'-0010': 'save userdata failed',
		//接收微信消息参数不全
		'-0011': 'wechat message params illegal',
		//连接mongodb数据库失败
		'-0012': 'mongodb not connect failed',
		//参数中未找到storeId
		'-0013': 'params storeId not found',
		//接收到的微信消息非来自微信服务器
		'-0014': 'msg not from wechat',
		//请求字符串无法转换为对象
		'-0015': 'request string not convert to object',
		//从微信服务器获取accessToken失败
		'-0016': 'get accessToken failed',
		//从redis读取accessToken失败
		'-0017': 'redis get accessToken data failed',
		//从微信服务器获取的json数据中未找到accessToken
		'-0018': 'get accessToken data not found token val',
		//上传的文件不符合要求
		'-0019': 'upload file illegal',
		//上传的文件移动到新目录失败
		'-0020': 'upload file not found store folder',
		//上传的文件的MIME类型是不允许上传的类型
		'-0021': 'upload file content-type illegal',
		//需要触发的接口参数未指定
		'-0022': 'triggerInterface params not found',
		//存储accessToken到redis失败
		'-0023': 'save accessToken to redis failed',
		//设置accessToken的生命周期失败
		'-0024': 'set accessToken expire failed',
		//WebSocket端收到了非JSON数据的消息
		'-0025': 'WebSocket receive msg is not json',
		//WebSocket端与服务端未进行配对
		'-0026': 'WebSocket not pair',
		//WebSocket广播消息失败
		'-0027': 'WebSocket broadcast failed',
		//客服未登录不允许配对WebSocket连接
		'-0028': 'service not logined',
		//客服消息处理中无法连接到对应商户的数据库
		'-0029': 'service not connect db',
		//从店铺数据库读取授权客服列表失败
		'-0030': 'get allowServices failed',
		//未授权此客服
		'-0031': 'service permission denied',
		//参数不足无法判别数据是否重复
		'-0032': 'params not check msg repeat',
		//从redis读取msgId失败
		'-0033': 'get msgId failed',
		//往redis存入msgId以及消息生成时间戳失败
		'-0034': 'save msgId-CreateTime failed',
		//从redis读取FromUserName + CreateTime失败
		'-0035': 'get FromUserName-CreateTime failed',
		//往redis存入msgId以及消息生成时间戳失败
		'-0036': 'save FromUserName-CreateTime failed',
		//获取storeId和tableNum和userId失败
		'-0037': 'get storeId or userId failed',
		//设置redis客服会话失败
		'-0038': 'set redis service session failed',
		//读取会话链失败
		'-0039': 'get msg:userId->storeId failed',
		//查询商户信息失败
		'-0040': 'get storeInfo failed',
		//array2obj将数据库信息转换为对象失败
		'-0041': 'array2obj failed',
		//WebSocket收到的消息中未找到接口参数
		'-0042': 'wsMsg interface params not found',
		//WebSocket中调用的接口文件不存在
		'-0043': 'wsMsg interface not found',
		//连接公用common数据库失败
		'-0044': 'connect common db failed',
		//存储3rdSession到redis失败
		'-0045': 'save 3rdSession to redis failed',
		//mongodb查找用户列表失败
		'-0046': 'select users failed',
		//mongodb更新用户信息失败
		'-0047': 'update userData failed',
		//mongodb查找自动回复列表失败
		'-0048': 'select autoReplyList failed',
		//服务员回复用户消息失败，参数不足
		'-0049': 'service reply msg failed',
		//微信服务器繁忙无法回复用户消息
		'-0050': 'wechat server busy',
		//回复消息时accessToken不正确
		'-0051': 'sendMsg accessToken not incorrect',
		//非法的凭证类型
		'-0052': 'token type forbidden',
		//回复用户消息时的openId非法
		'-0053': 'openId forbidden',
		//回复消息超时
		'-0054': 'reply msg timeout',
		//回复消息额度不足
		'-0055': 'reply credit no enough',
		//API功能未授权，小程序可能未获得此接口
		'-0056': 'api not auth',
		//调用获取文件接口的参数不足
		'-0057': 'download file params enough',
		//不是合法的下载类型如需开放此类型应在config中往suffixMap添加对应项
		'-0058': 'download fileMime not allow',
		//download接口获取的文件不存在
		'-0059': 'download file not found',
		//download接口获取文件内容失败
		'-0060': 'get download file failed',
		//websocket请求调用的接口参数中不存在data
		'-0061': 'WebSocket request params not data',
		//获取未读消息推送失败
		'-0062': 'get unreadMsg failed',
		//获取菜单列表数据失败
		'-0063': 'get foodMenu failed',
		//删除菜品失败
		'-0064': 'del food failed',
		//上架菜品失败
		'-0065': 'push food failed',
		//下架菜品失败
		'-0066': 'pull food failed',
		//从数据库读取商户菜品类型失败
		'-0067': 'get store foodType failed',
		//插入菜品到数据库失败
		'-0068': 'insert food failed',
		//生成随机字符串失败
		'-0069': 'create random str failed',
		//更新菜品时缺少必须参数
		'-0070': 'update food lack',
		//更新菜品数据到数据库时失败
		'-0071': 'update foodData failed',
		//查询所有自动回复数据失败
		'-0072': 'get all autoReplyList failed',
		//添加自动回复数据失败
		'-0073': 'insert autoReplyItem failed',
		//修改自动回复数据失败
		'-0074': 'update autoReplyItem failed',
		//删除自动回复数据失败
		'-0075': 'delete autoReplyItem failed',
		//对自动回复数据进行操作时参数不正确
		'-0076': 'use autoReplyItem params error',
		//将上传的文件从临时文件夹转移到保存路径时失败
		'-0077': 'upload file move to savePath failed',
		//查询聊天记录失败
		'-0078': 'find chatList failed',
		//更新聊天记录接收状态失败
		'-0079': 'update chat receive status failed',
		//查询足迹时未发现登录code参数
		'-0080': 'get userData failed',
		//获取用户ID失败
		'-0081': 'get userId failed',
		//提交的订单中不存在任何菜品
		'-0082': 'order is empty',
		//新增订单失败
		'-0083': 'creare order failed',
		//订单中可能存在重复菜品ID
		'-0084': 'order foodId repeat',
		//创建订单号失败
		'-0085': 'create orderId failed',
		//进行md5加密时出错
		'-0086': 'md5 crypt failed',
		//拼接支付签名字符串失败
		'-0087': 'link sign str failed',
		//订单数据转换为xml数据失败
		'-0088': 'orderData convert xml str failed',
		//请求微信同意下单接口失败
		'-0089': 'request wx place order interface failed',
		//转换xml为对象失败
		'-0090': 'xml convert to obj failed',
		//转换对象为xml失败
		'-0091': 'obj conver to xml failed',
		//统一下单接口返回了错误
		'-0092': 'wx place order interface back error',
		//无法识别支付商户
		'-0093': 'pay store not found',
		//检查数据来源失败
		'-0094': 'check wxData failed',
		//从微信服务器发送过来的支付结果数据错误
		'-0095': 'payResultData error',
		//从数据库读取商户服务信息列表失败
		'-0096': 'find storeFunInfo failed',
		//服务消息接口参数不足
		'-0097': 'storeFun params enough',
		//获取客服个数失败
		'-0098': 'get service sum failed',
		//记录未读服务通知时出错
		'-0099': 'save no receive service notify failed',
		//获取未读服务通知列表失败
		'-0100': 'get no receive service notify failed',
		//清除所有未读服务通知列表失败
		'-0101': 'clear no receive service notify failed',
		//查询未完成订单失败
		'-0102': 'get no done orders failed',
		//结束订单接口参数不足
		'-0103': 'orderDone params enough',
		//确认结单时发现用户未完成支付操作
		'-0104': 'user pay unfinished in order done',
		//确认结单时发现此订单已经结单
		'-0105': 'order is done',
		//确认结单时发现商家已经收到订单的款项
		'-0106': 'store is received order money in order done',
		//确认结单时更新微信支付的订单的状态失败
		'-0107': 'wxPay order update status failed',
		//确认结单时更新现金支付的订单的状态失败
		'-0108': 'cashPay order update status failed',
		//确认结单时得到了一个错误的支付类型
		'-0109': 'pay mode error',
		//订单用户不匹配
		'-0110': 'order user not pair',
		//确认结单时查询对应订单数据失败,
		'-0111': 'order done find order data failed',
		//确认订单时没有找到对应订单
		'-0112': 'order done not find order',
		//同步上菜状态接口参数不足
		'-0113': 'sync order serving params enough',
		//同步上菜状态接口查询订单信息时出错
		'-0114': 'sync order serving find order data failed',
		//同步上菜状态接口查找不到对应订单
		'-0115': 'sync order serving order not found',
		//同步上菜状态接口对应的订单中找不到需要操作的菜品
		'-0116': 'sync order serving order food not found',
		//同步上菜状态接口更新上菜状态到数据库失败
		'-0117': 'sync order serving update order data failed',
		//获取商户附加物品失败
		'-0118': 'get store attach goods failed',
		//查询所有未提现订单接口参数不足
		'-0119': 'find no receive money order params enough',
		//查询所有未提现订单失败
		'-0120': 'find no receive money order failed',
		//触发提现接口的参数不足
		'-0121': 'withdrawCash params enough',
		//查找需要提现的订单失败
		'-0122': 'find withdrawCash order failed',
		//提现的订单数量和数据库中查询的订单数量不一致
		'-0123': 'withdrawCash order count not equal to database order',
		//提现的订单id中包含已提现或提现中的订单id
		'-0124': 'an order has been raised',
		//获取用户ID失败
		'-0125': 'get user id failed',
		//设置提现订单的提现ID失败
		'-0126': 'set withdrawCash order withdrawCashId failed',
		//连接到公共数据库失败
		'-0127': 'connect to common database failed',
		//向公共数据库的提现列表插入提现记录失败
		'-0128': 'insert withdrawCash to common database failed',
		//查询提现详情接口参数不足
		'-0129': 'get withdrawCash detail parame enough',
		//查找有提现ID的订单失败
		'-0130': 'find withdrawCash order failed',
		//在公共数据库中查找提现记录失败
		'-0131': 'common db find withdrawCashLogs failed',
		//未找到此提现ID的订单
		'-0132': 'withdrawCashId order not found',
		//未找到此提现ID的提现记录
		'-0133': 'withdrawCash log not found',
		//查询提现者时出现错误
		'-0134': 'find withdrawCash person failed',
		//获取二维码的参数不足
		'-0135': 'getQRCode params enough',
		//获取二维码时出现错误
		'-0136': 'getQRCode failed',
		//获取验证码时没有提供随机值rn
		'-0137': 'getVcode params enough',
		//获取验证码时存储验证码到redis失败
		'-0138': 'save vcode failed',
		//redis设置验证码的生命周期失败
		'-0139': 'set vcode expire failed',
		//后台管理登录的参数不足
		'-0140': 'adminLogin params enough',
		//redis读取缓存验证码失败
		'-0141': 'redis get vcode failed',
		//后台管理登录验证码不正确
		'-0142': 'adminLogin vcode error',
		//查询管理员数据库失败
		'-0143': 'select admin database failed',
		//后台管理登录用户名或密码错误
		'-0144': 'adminLogin userName or userPwd error',
		//存放后台管理登录态到redis失败
		'-0145': 'save adminLogin session failed',
		//权限激活参数错误
		'-0146': 'activation params error',
		//权限激活获取用户ID失败
		'-0147': 'activation get userId failed',
		//权限激活获取激活码信息失败
		'-0148': 'activation redis get registerCode Info failed',
		//权限激活激活码无效
		'-0149': 'invalid activation registerCode params',
		//权限激活查找允许的管理失败
		'-0150': 'activation find allowServices failed',
		//权限激活新增管理操作失败
		'-0151': 'activation add allowServices failed',
		//激活管理建立商户失败
		'-0152': 'activation createStore failed',
		//创建商户数据库失败
		'-0153': 'create storeDB failed',
		//连接到商户数据库失败
		'-0154': 'connect storeDB failed',
		//往公共数据库中插入新商户失败
		'-0155': 'insert new store to common failed',
		//插入商户信息到商户数据库失败
		'-0156': 'insert new storeInfo to storeDB failed',
		//插入菜品类型到商户数据库失败
		'-0157': 'insert new store foodTypes to storeDB failed',
		//此商户已激活
		'-0158': 'store is registered',
		//删除已使用激活码失败
		'-0159': 'del registered code failed',
		//设置商户资料接口参数不足
		'-0160': 'setStoreInfo params enough',
		//更新商户数据库的商户资料失败
		'-0161': 'update storeInfo failed',
		//更新公共数据库的商户资料失败
		'-0162': 'update common storeInfo failed',
		//设置个人资料接口参数不足
		'-0163': 'setRoleInfo params enough',
		//更改允许服务员资料失败
		'-0164': 'update service info failed',
		//不可降级自己的权限
		'-0165': 'reduce permission failed',
		//获取角色列表失败
		'-0166': 'get allowServices failed',
		//已存在同样的角色名，不可重复添加
		'-0167': 'serviceName exists add failed',
		//生成六位激活码失败
		'-0168': 'create registerCode failed',
		//存放激活码到redis失败
		'-0169': 'save registerCode to redis failed',
		//设置激活码生命周期失败
		'-0170': 'set register expire failed',
		//删除的角色未指定serviceId
		'-0171': 'del service serviceId not found',
		//redis读取管理员信息失败
		'-0172': 'redis get service info failed',
		//没有足够的权限删除角色
		'-0173': 'del service permission denied',
		//查找对应的管理角色失败
		'-0174': 'find service admin failed',
		//删除角色失败
		'-0175': 'delete service failed',
		//获取指定天的订单列表接口参数不足
		'-0176': 'get day orderList params enough',
		//获取指定天的订单列表失败
		'-0177': 'get day orderList failed',
		//获取订单详情接口参数不足
		'-0178': 'get orderDetail failed',
		//添加附加物品接口参数不足
		'-0179': 'add goods params enough',
		//添加附加物品失败
		'-0180': 'add goods failed',
		//获取附加物品列表失败
		'-0181': 'get goodsList failed',
		//删除附加物品接口参数不足
		'-0182': 'del goods params enough',
		//删除附加物品失败
		'-0183': 'del goods failed',
		//修改附加物品接口参数不足
		'-0184': 'edit goods params enough',
		//更改附加物品数据失败
		'-0185': 'edit goods failed',
		//查询未现金支付订单用户失败
		'-0186': 'find user not cashPay order failed',
		//新增现金支付订单失败
		'-0187': 'add new cashPay order failed',
		//确认现金支付已完成接口参数不足
		'-0188': 'checkCasgPayDone params enough',
		//商户尚未确认收款
		'-0189': 'store not check cashPay done',
		//获取管理员登录状态失败
		'-0190': 'get adminLogin status failed',
		//管理员未登录
		'-0191': 'admin not login',
		//生成商户激活码失败
		'-0192': 'create new store registerCode failed',
		//存储商户激活码失败
		'-0193': 'save store registerCode failed',
		//获取商家激活码接口参数不足
		'-0194': 'get store registerCode params enough',
		//不存在此用户
		'-0195': 'user not found',
		//获取用户数据失败
		'-0196': 'get user data failed',
		//更改用户数据接口参数不足
		'-0197': 'update user data params enough',
		//修改用户数据失败
		'-0198': 'update user data failed',
		//获取用户消费记录列表接口参数不足
		'-0199': 'getMyPayList params enough',
		//查询用户消费订单列表失败
		'-0200': 'find user orderList failed',
		//查找服务列表失败
		'-0201': 'find service list failed',
		//添加服务接口参数不足
		'-0202': 'add service params enough',
		//生成服务ID失败
		'-0203': 'create funId failed',
		//添加服务失败
		'-0204': 'add service failed',
		//删除服务接口参数不足
		'-0205': 'del service params enough',
		//删除服务失败
		'-0206': 'del service failed',
		//修改服务名称接口参数不足
		'-0207': 'update service name params enough',
		//修改服务名称失败
		'-0208': 'update service name failed',
		//上移服务接口参数不足
		'-0209': 'up service params enough',
		//上移服务失败
		'-0210': 'up service failed',
		//下移服务接口参数不足
		'-0211': 'down service params enough',
		//下移服务失败
		'-0212': 'down service failed',
		//新增客户反馈接口参数不足
		'-0213': 'add feedBack params enough',
		//新增客户反馈失败
		'-0214': 'add feedBack failed',
		//设置商户银行卡信息接口数据不足
		'-0215': 'set bankCardInfo params enough',
		//设置商户银行卡信息失败
		'-0216': 'set bankCardInfo failed'
	}
	//默认为未知错误
	var errText = 'unknown error';
	//判断是否存在错误码的对应的错误内容
	if(errList[errCode]) {
		//将错误字符串设置为错误码对应的字符串
		errText = errList[errCode];
	}
	//返回加工过的错误json字符串
	deferred.resolve(JSON.stringify({
		errCode: errCode,
		errMsg: errText
	}));
	return deferred.promise;
}

//发起GET请求函数
var get = function(url, reqData) {
	var deferred = Q.defer();
	//将请求数据转换成GET请求字符串
	reqData = qs.stringify(reqData);
	//将请求字符串与url连接
	url = url + '?' + reqData;
	console.log('发起GET请求' + url);
	//发起GET请求
	request(url, function(err, res, body) {
		if(err) {
			//请求错误
			deferred.reject(err);
		}
		else if(res.statusCode == 200) {
			//状态码为200请求成功
			//判断是否为json字符串
			if(isJson(body)) {
				//将json字符串转换成对象
				body = JSON.parse(body);
			}
			//返回得到的数据
			deferred.resolve(body);
		}
		else {
			//状态码非200
			console.log('GET请求收到错误返回', err);
			deferred.reject(err);
		}
	});
	return deferred.promise;
}

//发起POST请求函数
var post = function(url, method, reqData) {
	var deferred = Q.defer();
	console.log('发起POST请求' + url);
	//发起POST请求
	request({
		url: url,
		method: method,
		json: true,
		headers: {
			'Content-Type': 'application/json; charset=utf-8',
		},
		//将数据转换成json字符串传输
		body: reqData
	}, function(err, res, body) {
		if(err) {
			//请求失败
			deferred.reject(err);
		}
		else if(res.statusCode == 200) {
			//返回得到的数据
			deferred.resolve(body);
		}
		else {
			//状态码非200
			console.log('POST请求收到错误返回', err);
			deferred.reject(err);
		}
	});
	return deferred.promise;
}

//对象内容合并函数
var objMerge = function(obj, mergeObj) {
	var deferred = Q.defer();
	//获取被合并对象内元素个数
	var sum = Object.keys(mergeObj).length;
	if(sum == 0) {
		deferred.resolve(obj);
	}
	for(var key in mergeObj) {
		//取出对应key的值设置到合并对象中
		obj[key] = mergeObj[key];
		//判断是否已经合并完成
		if(--sum == 0) {
			//返回合并完成的对象
			deferred.resolve(obj);
		}
	}
	return deferred.promise;
}

//从数组中查找键值对函数
var array2obj = function(array) {
	var deferred = Q.defer();
	//尝试将数据库得到的数组转换成一个对象
	try {
		//初始化一个对象
		var obj = {};
		if(array.length == 0) {
			deferred.resolve(obj);
		}
		//遍历数组
		for(var index in array) {
			//遍历每个数组元素的对象
			for(var key in array[index]) {
				//排除_id
				if(key == '_id') {
					continue;
				}
				//赋值给对象
				obj[key] = array[index][key];
			}
			//判断是否已经遍历完全部数组元素
			if(index == array.length - 1) {
				//返回对象
				deferred.resolve(obj);
			}
		}
	}
	catch(e) {
		console.log(e);
		//转换失败返回错误
		deferred.reject(e);
	}
	return deferred.promise;
}

var objEqual = function(obj1, obj2) {
	var deferred = Q.defer();
	var objIndex = 0;
	var objLength = Object.keys(obj1).length;
	if(objLength == 0 || Object.keys(obj2).length == 0) {
		deferred.reject();
	}
	for(var key in obj1) {
		if(obj1[key] != obj2[key]) {
			deferred.reject();
			break;
		}
		if(++objIndex == objLength) {
			deferred.resolve();
		}
	}
	return deferred.promise;
}

//将xml字符串转换为对象函数
var xml2obj = function(xmlData) {
	var deferred = Q.defer();
	//实例化一个xml转换对象
	var parser = new xml2js.Parser();
	//将xml字符串转换为对象
	parser.parseString(xmlData, function(err, objData) {
		//判断转换时是否发生错误
		if(err) {
			console.log(err);
			deferred.reject();
		}
		else {
			//转换成功并返回对象
			deferred.resolve(objData);
		}
	});
	return deferred.promise;
}

//将对象转换为xml字符串函数
var obj2xml = function(objData) {
	var deferred = Q.defer();
	//尝试构造xml字符串
	try {
		//实例化一个xml构造器
		var builder = new xml2js.Builder();
		//将对象构造成一个xml字符串
		var xmlData = builder.buildObject(objData);
		//构造成功返回xml字符串
		deferred.resolve(xmlData);
	}
	catch(e) {
		//构造xml字符串失败
		console.log(e);
		deferred.reject();
	}
	return deferred.promise;
}

//触发接口函数
var triggerInterface = function(interfaceName, getData, postData, config, _redis, db) {
	var deferred = Q.defer();
	//组合接口目录路径
	var interfacePath = config.basePath + '/interfaces/' + interfaceName + '.js';
	//判断接口文件是否存在
	fsExists(interfacePath).then(function() {
		//引入接口
		var _interface = require(interfacePath);
		//触发接口的入口函数
		_interface.index(getData, postData, config, _redis, db).then(function(data) {
			//接口调用成功返回数据
			deferred.resolve(data);
		}, function(errCode) {
			//接口调用失败返回错误码
			deferred.reject(errCode);
		});
	}, function() {
		//返回接口文件不存在
		deferred.reject('-0001');
	});
	return deferred.promise;
}

var createRandomStr = function(strlen) {
	var deferred = Q.defer();
	try {
		//存储结果的字符串
		var randomStr = '';
		//用于生成随机字符串的素材
		var material = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
		//获得种子随机生成器
		let random = seedrandom(Date.now());
		//循环生成长度
		for(var i = 0;i < strlen;i++) {
			//添加在素材字符串随机找到的字符
			randomStr += material[parseInt(random() * 61)];
		}
		//返回生成的随机字符串
		deferred.resolve(randomStr);
	}
	catch(e) {
		deferred.reject();
	}
	return deferred.promise;
}

//对字符串进行md5加密
var md5 = function(str) {
	var deferred = Q.defer();
	try {
		cryptStr = crypto.createHash('md5').update(str).digest('hex');
		deferred.resolve(cryptStr);
	}
	catch(e) {
		console.log(e);
		deferred.reject();
	}
	return deferred.promise;
}

//检查数据是否来自微信服务器函数
var checkWxData = function(data, payKey) {
	var deferred = Q.defer();
	var sign = '';
	var tempStr = '';
	var dataKeys = Object.keys(data);
	dataKeys = dataKeys.sort();
	for(var index in dataKeys) {
		if(dataKeys[index] == 'sign') {
			sign = data[dataKeys[index]];
			continue;
		}
		tempStr += dataKeys[index] + '=' + data[dataKeys[index]] + '&';
	}
	tempStr += ('key=' + payKey);
	console.log('待md5验证字符串', tempStr);
	md5(tempStr).then(function(signStr) {
		if(sign == signStr.toUpperCase()) {
			deferred.resolve(true);
		}
		else {
			deferred.resolve(false);
		}
	}, function() {
		deferred.reject();
	});
	return deferred.promise;
}

var add = function(a, b) {
	let deferred = Q.defer();
	let c, d, e, result;
	try {
		c = a.toString().split('.')[1].length;
	}
	catch(e) {
		c = 0;
	}
	try {
		d = b.toString().split('.')[1].length;
	}
	catch(e) {
		d = 0;
	}
	e = Math.pow(10, Math.max(c, d));
	result = a * e + b * e;
	result = result / e;
	deferred.resolve(result);
	return deferred.promise;
}

//检查管理员是否登录
let checkAdminLogin = function(redis, session) {
	redis.get(session).then(function(data) {
		if(data) {
			data = JSON.parse(data);
			if(data.openId) {
				deferred.resolve({
					userName: data.openId,
					loginTimestamp: data.sessionKey
				});
			}
			else {
				//管理员未登录
				deferred.reject('-0191');
			}
		}
		else {
			//管理员未登录
			deferred.reject('-0191');
		}
	}, function() {
		//获取管理员登录状态失败
		deferred.reject('-0190');
	});
}

//暴露接口
module.exports = {
	createHttpServer: createHttpServer,
	isPost: isPost,
	isGet: isGet,
	isSet: isSet,
	isEmpty: isEmpty,
	isString: isString,
	isJson: isJson,
	isArray: isArray,
	execShell: execShell,
	string2obj: string2obj,
	fsExists: fsExists,
	fsMkdir: fsMkdir,
	getError: getError,
	get: get,
	post: post,
	objMerge: objMerge,
	array2obj: array2obj,
	objEqual: objEqual,
	xml2obj: xml2obj,
	obj2xml: obj2xml,
	triggerInterface: triggerInterface,
	createRandomStr: createRandomStr,
	md5: md5,
	checkWxData: checkWxData,
	add: add,
	checkAdminLogin: checkAdminLogin
}